-- PRAGMA standard control signal mapping:
-- clk								=> clk
-- clk_48k							=> clk_48k
-- reset								=> reset
-- PAY ATTENTION:					RESET IS ACTIVE LOW
-- control_in	(0) 				=> reverb_enable
--					(7 downto 1) 	=> UNUSED
--
--	control_out	(0)				<= enable
--					(3 downto 1)	<= UNUSED
-- 
-- PCM_data_in_right				=> PCM_data_in_right
-- PCM_data_in_left				=> PCM_data_in_left
-- PCM_data_out_right			<= PCM_data_out_right
-- PCM_data_out_left				<= PCM_data_out_left

library ieee;
use ieee.std_logic_signed.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.delay_pkg.all;

entity PRM_time_1 is
  port(
    clk				: in std_logic;
	 clk_48k			: in std_logic;
    reset			: in std_logic;
	 
	 control_in		: in std_logic_vector(7 downto 0);
	 control_out	: out std_logic_vector(3 downto 0);
	 
    PCM_data_in_right	: in std_logic_vector(15 downto 0);
	 PCM_data_in_left		: in std_logic_vector(15 downto 0);
    PCM_data_out_right	: out std_logic_vector(15 downto 0);
	 PCM_data_out_left	: out std_logic_vector(15 downto 0)
    );
end entity PRM_time_1;

architecture structural of PRM_time_1 is
  component comb is
	 generic(
		delay						: integer);
	 port(
      clk						: in std_logic;
		clk_48k					: in std_logic;
      reset						: in std_logic;
		
		control_in				: in std_logic_vector(7 downto 0);
		control_out				: out std_logic_vector(3 downto 0);
		
      PCM_data_in				: in std_logic_vector(15 downto 0);
		PCM_data_out			: out std_logic_vector(15 downto 0)
      );
  end component comb;
  
  component allpass is
	 generic(
		delay						: integer);
	 port(
      clk						: in std_logic;
		clk_48k					: in std_logic;
      reset						: in std_logic;
		
		control_in				: in std_logic_vector(7 downto 0);
		control_out				: out std_logic_vector(3 downto 0);
		
      PCM_data_in				: in std_logic_vector(15 downto 0);
		PCM_data_out			: out std_logic_vector(15 downto 0)
      );
  end component allpass;
  
  signal reverb_enable			: std_logic;
  
  signal control_in_left		: std_logic_vector(7 downto 0);
  signal control_out_left_0	: std_logic_vector(3 downto 0);
  signal control_out_left_1	: std_logic_vector(3 downto 0);
  signal control_out_left_2	: std_logic_vector(3 downto 0);
  signal control_out_left_3	: std_logic_vector(3 downto 0);
  signal control_out_left_4	: std_logic_vector(3 downto 0);
  signal control_out_left_5	: std_logic_vector(3 downto 0);
  
  signal PM_data_0				: std_logic_vector(15 downto 0);
  signal PM_data_1				: std_logic_vector(15 downto 0);
  signal PM_data_2				: std_logic_vector(15 downto 0);
  signal PM_data_3				: std_logic_vector(15 downto 0);
  
  signal combed					: std_logic_vector(15 downto 0);
  signal allpass_in				: std_logic_vector(17 downto 0);
  signal trimmed					: std_logic_vector(15 downto 0);
  signal allpassed				: std_logic_vector(15 downto 0);
  signal	PCM_data_out			: std_logic_vector(16 downto 0);
   
begin

	reverb_enable	<= control_in(0);
	
	control_out(0)	<= reverb_enable;
	control_out(1)	<= control_in(1);
	control_out(2)	<= control_in(2);
	control_out(3)	<= control_in(3);
	
	comb_0_left: comb 	generic map(
											delay					=> 1511)			--1511 = prime (31 ms)
								port map (	
											clk 					=> clk,
											clk_48k				=> clk_48k,
											reset 				=> reset,
								
											control_in			=> control_in_left,
											control_out			=> control_out_left_0,

											PCM_data_in			=> PCM_data_in_left,
											PCM_data_out		=> PM_data_0
											);
											
	comb_1_left: comb 	generic map(
											delay					=> 1783)			--1783 = prime (37 ms)
								port map (	
											clk 					=> clk,
											clk_48k				=> clk_48k,
											reset 				=> reset,
								
											control_in			=> control_in_left,
											control_out			=> control_out_left_1,

											PCM_data_in			=> PCM_data_in_left,
											PCM_data_out		=> PM_data_1
											);
											
	comb_2_left: comb 	generic map(
											delay					=> 1979)			--1979 = prime (41 ms)
								port map (	
											clk 					=> clk,
											clk_48k				=> clk_48k,
											reset 				=> reset,
								
											control_in			=> control_in_left,
											control_out			=> control_out_left_2,

											PCM_data_in			=> PCM_data_in_left,
											PCM_data_out		=> PM_data_2
											);
											
	comb_3_left: comb 	generic map(
											delay					=> 2269)			--2063 = prime (43 ms)
								port map (	
											clk 					=> clk,
											clk_48k				=> clk_48k,
											reset 				=> reset,
								
											control_in			=> control_in_left,
											control_out			=> control_out_left_3,

											PCM_data_in			=> PCM_data_in_left,
											PCM_data_out		=> PM_data_3
											);
											
	allpass_0_left: allpass	generic map(
											delay					=> 577)			--577 = prime (12 ms)
									port map (	
											clk 					=> clk,
											clk_48k				=> clk_48k,
											reset 				=> reset,
								
											control_in			=> control_in_left,
											control_out			=> control_out_left_4,

											PCM_data_in			=> allpass_in(15 downto 0),
											PCM_data_out		=> trimmed
											);
	
	allpass_1_left: allpass	generic map(
											delay					=> 919)			--919 = prime (19 ms)
									port map (	
											clk 					=> clk,
											clk_48k				=> clk_48k,
											reset 				=> reset,
								
											control_in			=> control_in_left,
											control_out			=> control_out_left_5,

											PCM_data_in			=> trimmed,
											PCM_data_out		=> allpassed
											);
  
  PCM_data_out_left <= PCM_data_out(15 downto 0);
  
  p_left: process(clk, reset)
  begin
    if (reset = '0') then                   --RESET ACTIVE LOW
      PCM_data_out 	<= (others => '0');
		PCM_data_out_right 	<= (others => '0'); 
    elsif (clk'event and clk = '1') then    --POSITIVE EDGE
		if (reverb_enable = '1') then
			combed				<= shr(PM_data_0,"010") 
										+ shr(PM_data_1,"010")
										+ shr(PM_data_2,"010")
										+ shr(PM_data_3,"010");
			allpass_in			<= combed(15 downto 1) * "011";	-- MAX(combed) = 2/3*(in) so rescale to ((2/3)/2)*3 = 1(in)

			--PCM_data_out <= PCM_data_in_left(15 downto 3) * "0111" + allpassed(15 downto 3);	--1/8 reverb contribution
			PCM_data_out	<= PCM_data_in_left(15 downto 1) * "01" + allpassed(15 downto 1);		--1/2 reverb contribution
		else
			PCM_data_out <= PCM_data_in_left(15) & PCM_data_in_left;
		end if;
	 end if;
  end process;

end architecture structural;
